﻿using DotNetty.Framework;
using DotNetty.Framework.BaseModel;
using iTool.Connector.CommandOfParameter;
using iTool.Connector.ModelOfRequest;
using DotNetty.OrleansClient;
using Grain.Interfaces;
using iTool.ClusterComponent;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace iTool.Connector.HttpWorkers
{
    public class InvokeFunctionWorker : IHttpWorker
    {
        iToolConnectorProvider iClient;
        public InvokeFunctionWorker(iToolConnectorProvider iClient)
        {
            this.iClient = iClient;
        }

        public int SecondOfTimeOut { get; set; } = 10;

        public async Task DoWorking<THttpContext>(THttpContext context) where THttpContext : AbstractHttpContext, new()
        {
            var parameter = (context as FunctionHttpContext).GetParameter<CloudFunctionParameterOfHttpRuning>();

            object result;

            iToolClusterHostClient cluster = this.iClient.GetClusterClient();
            result = await this.InvokeFunctionAsync(cluster, parameter);

            context.ResponseBody = JsonConvert.SerializeObject(result);
        }

        public bool IsUseWorking<THttpContext>(THttpContext context) where THttpContext : AbstractHttpContext, new()
        {
            var parameter = (context as FunctionHttpContext).GetParameter<CloudFunctionParameterOfHttpRuning>();
            return parameter != null;
        }

        private async Task<object> InvokeFunctionAsync(
            iToolClusterHostClient cluster,
            CloudFunctionParameterOfHttpRuning parameter)
        {

            object result;

            if (string.IsNullOrWhiteSpace(parameter.ModuleName))
                return new
                {
                    Code = 400,
                    Error = "ModuleName is null"
                };

            ICloudRunningFunctionService moduleFunction = cluster.GetService<ICloudRunningFunctionService>(parameter.ModuleName);

            // 测查是否使用模块
            if (parameter.IsUseState)
            {
                if (string.IsNullOrWhiteSpace(parameter.ExportedFunctionName))
                    return new
                    {
                        Code = 400,
                        Error = "ExportedFunctionName is null"
                    };

                if (string.IsNullOrWhiteSpace(parameter.StateKey))
                    return new
                    {
                        Code = 400,
                        Error = "StateKey is null"
                    };

                // 获取模块地址
                var modulePath = await moduleFunction.GetFunctionModulePath();

                if (string.IsNullOrWhiteSpace(modulePath))
                    return new
                    {
                        Code = 400,
                        Error = "module is null"
                    };

                var module = cluster.GetService<ICloudRunningFunctionContainStateService>($"{parameter.StateKey}_{modulePath}");

                result = await module.InvokeExport(
                    parameter.ExportedFunctionName.ToLower(),
                    parameter.Channel,
                    parameter.Parameters);
            }
            else
            {

                result =
                    string.IsNullOrWhiteSpace(parameter.ExportedFunctionName) ?
                    await moduleFunction.Invoke(parameter.Channel, parameter.Parameters)
                    :
                    await moduleFunction.InvokeExport(
                        parameter.Channel,
                        parameter.ExportedFunctionName.ToLower(),
                        parameter.Parameters);
            }

            return new
            {
                Code = 200,
                Body = result
            };
        }
    }
}
